package item48;

import java.math.BigDecimal;

/**
 * 第48条：如果需要精确的答案，请避免使用float和double
 */
public class Main01 {

    public static void main(String[] args) {
        /**
         * float、double类型主要是为了科学计算和工程计算而设计。
         * 它们执行二进制符点运算(binary floating-point arithmetic)
         * 这是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的。
         * float、double不应该被用于需要精确结果的场合。
         */

        // float、double类型尤其不适合用于货币计算

        System.out.println(1.03 - 0.42);
        System.out.println(1.00 - 9 * 0.10);
        double funds = 1.00;
        int itemsBought = 0;
        for (double price = 0.10; funds >= price; price += 0.10) {
            funds -= price;
            itemsBought++;
        }
        System.out.println(itemsBought + "items bought.");
        System.out.println("Change: $" + funds);

        // 使用bigDecimal、int或者long进行货币计算。

        final BigDecimal TEN_CENTS = new BigDecimal("0.10");
        int itemsBought2 = 0;
        BigDecimal funds2 = new BigDecimal("1.00");
        for (BigDecimal price = TEN_CENTS;
                funds2.compareTo(price) >= 0;
                price = price.add(TEN_CENTS)) {
            itemsBought2++;
            funds2 = funds2.subtract(price);
        }
        System.out.println(itemsBought2 + "items bought.");
        System.out.println("Change: $" + funds2);

        //bigdecimal有两个缺点：
        // 1.与使用基本运算类型相比，不方便
        // 2.慢

        int itemsBought3 = 0;
        int funds3 = 100;
        for (int price = 10; funds3 >= price; price += 10) {
            itemsBought3++;
            funds3 -= price;
        }
        System.out.println(itemsBought3 + "items bought.");
        System.out.println("Money left over: " + funds3 + " cents");

        // 使用bigDecimal允许完全控制舍入，每当一个操作涉及舍入的时候，它允许你从8种舍入模式选择其一。

        // 非常关心性能，所所涉及的数值不太大，就可以使用int或者long。
        // 如果数值范围没有超过9位十进制数字，就可以使用int;
        // 如果不超过18位数字，就可以使用long.
        // 如果数值可能超过18位数字，就必须使用BigDecimal

    }

}
